﻿using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System.Collections.Concurrent;
using Volo.Abp.DependencyInjection;

namespace Xms.Abp.Caching;

public class RedisCacheProvider : CacheProviderBase, ITransientDependency
{
    public override string Name => "Redis";

    public RedisCacheProvider(IAbpLazyServiceProvider lazyServiceProvider)
        : base(lazyServiceProvider)
    {
    }

    protected override IXmsCache GetOrAddCache(ConcurrentDictionary<string, IXmsCache> caches, string connectionString)
    {
        return GetOrAddCache(LazyServiceProvider, caches, connectionString);
    }

    internal static IXmsCache GetOrAddCache(IAbpLazyServiceProvider lazyServiceProvider, ConcurrentDictionary<string, IXmsCache> caches, string connectionString)
    {
        return caches.GetOrAdd(connectionString, s => CreateCache(lazyServiceProvider, connectionString));
    }

    internal static IXmsCache CreateCache(IAbpLazyServiceProvider lazyServiceProvider, string connectionString = null)
    {
        var opts = lazyServiceProvider.LazyGetRequiredService<IOptions<RedisCacheOptions>>().Value;
        var options = new RedisCacheOptions
        {
            Configuration = connectionString ?? opts.Configuration,
            ConfigurationOptions = opts.ConfigurationOptions,
            ConnectionMultiplexerFactory = opts.ConnectionMultiplexerFactory,
            InstanceName = opts.InstanceName,
            ProfilingSession = opts.ProfilingSession
        };
        return new XmsRedisCache(Options.Create(options), lazyServiceProvider.LazyGetRequiredService<IConfiguration>());
    }
}

public class RedisCacheProvider<TCacheContext> : CacheProviderBase<TCacheContext>, ICacheProvider<TCacheContext>
    where TCacheContext : CacheContext<TCacheContext>
{
    public RedisCacheProvider(IAbpLazyServiceProvider lazyServiceProvider)
        : base(lazyServiceProvider)
    {
    }

    public override string Name => "Redis";

    protected override IXmsCache GetOrAddCache(ConcurrentDictionary<string, IXmsCache> caches, string connectionString)
    {
        return RedisCacheProvider.GetOrAddCache(LazyServiceProvider, caches, connectionString);
    }
}
